home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / delicious_bookmarks-2.0.64-fx.xpi / components / nsYJSProfiler.js < prev    next >
Text File  |  2008-06-19  |  11KB  |  343 lines

  1. const nsISupports = Components.interfaces.nsISupports;
  2. const nsIYJSProfiler = Components.interfaces.nsIYJSProfiler;
  3.  
  4. var CC = Components.classes;
  5. var CI = Components.interfaces;
  6.  
  7. const CLASS_ID = Components.ID("D55713D4-3511-4b7a-8271-E41CE03943DB");
  8. const CLASS_NAME = "A generic profiler component coded in JS";
  9. const CONTRACT_ID = "@yahoo.com/YJSProfiler;1";
  10.  
  11.  
  12. const kHashPropertyBagContractID = "@mozilla.org/hash-property-bag;1";
  13. const kIWritablePropertyBag = Components.interfaces.nsIWritablePropertyBag;
  14. const HashPropertyBag = new Components.Constructor(kHashPropertyBagContractID, kIWritablePropertyBag);
  15.  
  16. var gXMLDoc=null;
  17. var gXMLRoot = null;
  18.  
  19. function LOG(msg)
  20. {
  21.   var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
  22.   consoleService.logStringMessage(msg);
  23. }
  24.  
  25.  
  26. function addDomElement(root, node, elementName, attributeList)
  27. {
  28.     try {
  29.         var element = root.createElement(elementName);
  30.         for (var i = 0; i< attributeList.length; i++){
  31.             var attrName = attributeList[i];
  32.             var attrValue = attributeList[i+1];
  33.             element.setAttribute(attrName, attrValue);
  34.             i++;
  35.         }
  36.         node.appendChild(element);
  37.     }catch(e) {LOG(e);}
  38. }
  39.  
  40. function addCallDataToXML(blockName,callID,timeStart,timeEnd,timeDiff)
  41. {
  42.     try{
  43.     var nodeList = gXMLDoc.getElementsByTagName(blockName);
  44.     if(nodeList.length==0){ // need to add the block
  45.             var blockAttrArray = new Array("name",blockName,"callCount","0","totalTime","0","averageTime","0");
  46.             addDomElement(gXMLDoc, gXMLRoot, blockName, blockAttrArray);
  47.     }
  48.     // get the blocknode again and add the call data
  49.     var blockNodeList = gXMLDoc.getElementsByTagName(blockName);
  50.     var blockNode = nodeList[0];
  51.     var callAttrArray = new Array("ID",callID,"startTime",timeStart,"endTime",timeEnd,"executionTime",timeDiff);
  52.     addDomElement(gXMLDoc, blockNode, callID, callAttrArray);
  53.     var callCount = blockNode.getAttribute("callCount")
  54.     var totalTime = blockNode.getAttribute("totalTime");
  55.     var newCallCount = parseInt(callCount)+1;
  56.     var newTotalTime = parseInt(totalTime)+timeDiff;
  57.     blockNode.setAttribute("callCount",newCallCount);
  58.     blockNode.setAttribute("totalTime",newTotalTime);
  59.     }catch(e) {LOG(e);}     
  60. }
  61.  
  62.  
  63. function createProfilingDataXML()
  64. {
  65.     try{
  66.      var xmlString='<ProfilingData></ProfilingData>';
  67.      var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].
  68.                createInstance(CI.nsIDOMParser);
  69.     gXMLDoc = parser.parseFromString(xmlString, "text/xml");
  70.     var nodeList = gXMLDoc.getElementsByTagName("ProfilingData");
  71.     gXMLRoot = nodeList.item(0);
  72.     }catch(e){LOG(e);}
  73. }
  74.  
  75. function serializeXMLToFile(xmlDocument, fileName, prefix, mismatchError)
  76. {
  77.     try {
  78.     var serializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"].
  79.                 createInstance(CI.nsIDOMSerializer);
  80.     var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
  81.                .createInstance(Components.interfaces.nsIFileOutputStream);
  82.     var file = Components.classes["@mozilla.org/file/directory_service;1"]
  83.                    .getService(Components.interfaces.nsIProperties)
  84.                    .get("ProfD", Components.interfaces.nsIFile); // get profile folder
  85.     file.append(fileName);   // filename
  86.     file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
  87.     foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
  88.     foStream.write(prefix,prefix.length);
  89.     var errorCount = parseInt(mismatchError);
  90.     if (errorCount > 0){
  91.             var errorArray = new Array("mismatchCount",errorCount);
  92.             addDomElement(gXMLDoc, gXMLRoot, "MISMATCH_ERROR", errorArray);
  93.     }    
  94.     serializer.serializeToStream(xmlDocument, foStream, "");
  95.     foStream.close();
  96.     }catch(e) {LOG(e);}
  97. }
  98.  
  99. /* map related functions*/                                                   
  100. function mapInsert(map,key,value)
  101. {
  102.     var success = false;
  103.     try{
  104.         map.setProperty(key,value);
  105.         success = true;
  106.     }catch (e){
  107.         LOG(e);
  108.     }
  109.     return success;    
  110. }
  111.     
  112. function mapFindValue(map,key)
  113. {
  114.     var value = null;
  115.     try{
  116.         value = map.getProperty(key);
  117.     }catch (e){
  118.         value=null;
  119.     }
  120.     return value;
  121. }
  122.     
  123. function mapGetSize(map)
  124. {
  125.     var e = map.enumerator;
  126.     var size=0;
  127.     while(e.hasMoreElements()){
  128.         size++;
  129.         e.getNext();
  130.     }
  131.     return size;    
  132. }
  133.  
  134. /*time related functions*/
  135. function getCurrentTime() { var d = new Date(); return d.getTime();}
  136. function storeStartTime(timeMap) {
  137.      mapInsert(timeMap,"timeStart",this.getCurrentTime());
  138. }
  139. function storeEndTime(timeMap) {
  140.      mapInsert(timeMap,"timeEnd",this.getCurrentTime());
  141. }
  142. function getStartTime(timeMap){ 
  143.     return mapFindValue(timeMap,"timeStart");
  144. }
  145. function getEndTime(timeMap){ 
  146.     return mapFindValue(timeMap,"timeEnd");
  147. }
  148.  
  149. /* Profile Class */
  150. function Profiler() {
  151.     _blockNameMap:null;
  152.  
  153.     this._blockNameMap=new HashPropertyBag();
  154.         
  155.     this.getInvocationIDMap=function(blockName){
  156.         return mapFindValue(this._blockNameMap,blockName);
  157.     },
  158.     
  159.     this.dumpMaps=function(){ // just for testing
  160.         var map = this._blockNameMap;
  161.         var e = map.enumerator;
  162.         while(e.hasMoreElements()){
  163.             var val = e.getNext().QueryInterface(CI.nsIProperty);
  164.             LOG(val.name);
  165.             var innermap = val.value;
  166.             var e1 = innermap.enumerator;
  167.             while(e1.hasMoreElements()){
  168.                 var val1 = e1.getNext().QueryInterface(CI.nsIProperty);
  169.                 LOG(val1.name);
  170.                 var timeMap = val1.value;
  171.                 var e2 = timeMap.enumerator;
  172.                 while(e2.hasMoreElements()){
  173.                     var val2 = e2.getNext().QueryInterface(CI.nsIProperty);
  174.                     LOG(val2.name +" : "+ val2.value);
  175.                 }    
  176.             }
  177.         }
  178.     },
  179.     /* traverses maps and converts to xml*/
  180.     this.traverseData=function(){
  181.  
  182.         var map = this._blockNameMap;
  183.         var e = map.enumerator;
  184.         while(e.hasMoreElements()){
  185.             var val = e.getNext().QueryInterface(CI.nsIProperty);
  186.             var blockName = val.name;
  187.             LOG(blockName);
  188.             var innermap = val.value;
  189.             var e1 = innermap.enumerator;
  190.             while(e1.hasMoreElements()){
  191.                 var val1 = e1.getNext().QueryInterface(CI.nsIProperty);
  192.                 var callID = val1.name;
  193.                 LOG(callID);
  194.                 var timeMap = val1.value;
  195.                 var timeStart = mapFindValue(timeMap,"timeStart");
  196.                 var timeEnd = mapFindValue(timeMap,"timeEnd");
  197.                 LOG("Start : "+ timeStart +" End : "+ timeEnd);
  198.                 var timeDiff = parseInt(timeEnd)-parseInt(timeStart);
  199.                 LOG("time taken ="+ timeDiff+" milliseconds");
  200.                 addCallDataToXML(blockName,callID,timeStart,timeEnd,timeDiff);
  201.                 }    
  202.             }
  203.         
  204.     },
  205.     /* traverses maps and converts to xml*/
  206.     this.calculateAverageTime=function(){
  207.         try{
  208.         var nodeList = gXMLRoot.childNodes;
  209.         
  210.         for(var i =0; i< nodeList.length;i++){
  211.             var node = nodeList[i];
  212.             var callCount = node.getAttribute("callCount")
  213.             var totalTime = node.getAttribute("totalTime");
  214.             var averageTime = parseInt(totalTime) / parseInt(callCount);
  215.             node.setAttribute("averageTime",averageTime);
  216.         }
  217.         }catch(e){LOG(e);}
  218.     },    
  219.     
  220.     this.startProfileBlock=function(blockName){
  221.         try{
  222.             if (!mapFindValue(this._blockNameMap,blockName)){
  223.                 mapInsert(this._blockNameMap,blockName, new HashPropertyBag());
  224.             }
  225.             var iMap = this.getInvocationIDMap(blockName);
  226.             var invocationID = (mapGetSize(iMap)+1); // start invocation IDs from 1
  227.             var invocationIDStr = "ID_"+invocationID;
  228.             var timeMap = new HashPropertyBag();
  229.             storeStartTime(timeMap);
  230.             mapInsert(iMap, invocationIDStr, timeMap);
  231.             return invocationID;
  232.         }catch(e){LOG(e);}
  233.     },
  234.     
  235.     this.endProfileBlock=function(blockName,invocationID){
  236.         try{
  237.             var invocationIDStr = "ID_"+invocationID;
  238.             var iMap = this.getInvocationIDMap(blockName);
  239.             var timeMap = mapFindValue(iMap,invocationIDStr);
  240.             if (timeMap!=null){
  241.                 storeEndTime(timeMap);
  242.             }
  243.         }
  244.         catch(e) {LOG(e);}
  245.     }
  246. };
  247.  
  248. function YJSProfiler() {
  249.     _profiler:null;
  250.     _profilingEnabled:null;
  251.     _fileName:null;
  252.     _mismatchError:null;
  253. }
  254.  
  255. // This is the implementation of component.
  256. YJSProfiler.prototype = {
  257.     initProfiler : function (fileName, profilingEnabled){
  258.         this._profilingEnabled = profilingEnabled;
  259.         if (!this._profilingEnabled) return;
  260.         this._fileName = fileName;
  261.         LOG("Init Profiler : "+fileName);
  262.         this._profiler= new Profiler();
  263.         this._mismatchError = 0;
  264.         
  265.     },
  266.     startProfileBlock:function (blockName){
  267.         if (!this._profilingEnabled) return;
  268.         this._mismatchError++;
  269.         return this._profiler.startProfileBlock(blockName);
  270.     },
  271.     endProfileBlock:function(blockName,invocationID){
  272.         if (!this._profilingEnabled) return;
  273.         this._mismatchError--;
  274.         this._profiler.endProfileBlock(blockName,invocationID);
  275.     },
  276.     
  277.     deInitProfiler:function(){
  278.         if (!this._profilingEnabled) return;
  279.         LOG("De Init Profiler")
  280.         //Convert data to xml and store to disk
  281.         createProfilingDataXML();
  282.         this._profiler.traverseData();
  283.         this._profiler.calculateAverageTime();
  284.         var prefix =
  285.         '<?xml version="1.0" encoding="ISO-8859-1"?><?xml-stylesheet type="text/xsl" href="ProfileInfoDisplay.xsl"?>';
  286.         serializeXMLToFile(gXMLDoc,this._fileName,prefix,this._mismatchError);
  287.         
  288.     },
  289.     QueryInterface: function(aIID) {
  290.         // add any other interfaces you support here
  291.         if (!aIID.equals(nsISupports) && !aIID.equals(nsIYJSProfiler))
  292.             throw Components.results.NS_ERROR_NO_INTERFACE;
  293.         return this;
  294.     }
  295. }
  296.  
  297. // Factory
  298. var YJSProfilerFactory = {
  299.   singleton:null,
  300.   createInstance: function (aOuter, aIID)
  301.   {
  302.     if (aOuter != null)
  303.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  304.      if (this.singleton == null){
  305.       this.singleton = new YJSProfiler();      
  306.       LOG("Profiler Component Created");
  307.      }
  308.      return this.singleton.QueryInterface(aIID);
  309.   }
  310. };
  311.  
  312. // Module
  313. var YJSProfilerModule = {
  314.   registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
  315.   { 
  316.     aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  317.     aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
  318.   },
  319.  
  320.   unregisterSelf: function(aCompMgr, aLocation, aType)
  321.   {
  322.     aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  323.     aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);        
  324.   },
  325.   
  326.   getClassObject: function(aCompMgr, aCID, aIID)
  327.   {
  328.     if (!aIID.equals(Components.interfaces.nsIFactory))
  329.       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  330.  
  331.     if (aCID.equals(CLASS_ID))
  332.       return YJSProfilerFactory;
  333.  
  334.     throw Components.results.NS_ERROR_NO_INTERFACE;
  335.   },
  336.  
  337.   canUnload: function(aCompMgr) { return true; }
  338. };
  339.  
  340. //module initialization
  341. function NSGetModule(aCompMgr, aFileSpec) { return YJSProfilerModule; }
  342.  
  343.